﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AppFx.Console
{
    /// <summary>
    /// Delegate used to call a command.
    /// </summary>
    /// <param name="command">Filled command.</param>
    public delegate void ExecuteDelegate(ConsoleCommand command);

    /// <summary>
    /// Represents an executable console-command.
    /// </summary>
    public class ConsoleCommand
    {
        #region Properties

        /// <summary>
        /// Gets or sets the name of the command.
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Gets or sets a list of aliases used for the command.
        /// </summary>
        public List<string> Aliases { get; set; }

        /// <summary>
        /// Gets or sets the parameters.
        /// </summary>
        public List<ConsoleParameter> Parameters { get; set; }

        /// <summary>
        /// Gets or sets the ExecuteDelegate called for execution of the command.
        /// </summary>
        public ExecuteDelegate Executor { get; set; }

        #endregion

        #region Constructors

        /// <summary>
        /// Creates a new ConsoleCommand.
        /// </summary>
        /// <param name="name">Name of the command.</param>
        /// <param name="aliases">Aliases of the command.</param>
        public ConsoleCommand(string name, ExecuteDelegate executor, IEnumerable<string> aliases)
        {
            Name = name;
            Executor = executor;

            Aliases = new List<string>();
            if (aliases != null)
                foreach (var alias in aliases)
                    Aliases.Add(alias);
        }

        #endregion

        #region Methods

        /// <summary>
        /// Executes the command.
        /// </summary>
        internal void Execute()
        {
            if (Parameters == null)
            {
                Executor.Invoke(this);
            }
            else
            {
                foreach (ConsoleParameter param in Parameters)
                {
                    bool validInput = false;
                    while (!validInput)
                    {
                        System.Console.WriteLine("Please enter a value for {0}(IsOptional: {1}('->' to skip), rule: {2}", param.Name, param.Optional, param.ValidationMessage);
                        string input = System.Console.ReadLine();

                        if (input == "->")
                            validInput = true;
                        else
                            param.Value = input;
                        validInput = param.Validate();
                    }
                }
                Executor.Invoke(this);
            }
        }

        #endregion
    }
}
